package cn.aylog.simpleStack;

import java.util.Arrays;
import java.util.Stack;

/**
 * 计算器底层实现
 *  计算 1+2+3+4*5 = 26
 */
public class CaculatorDemo {
    public static void main(String[] args) {
        String express = "1+2+3+4*6/2-8*5-6";
        System.out.println(calc(express));
    }

    /**
     * 使用栈实现四则运算
     */
    public static double calc(String exp) {
        // 表达式的有效性校验
        boolean flag = exp.matches("^\\d+([ ]*[*/+-]?[ ]*\\d+)+?$");
        if(!flag) {
            System.out.println("无效的表达式~");
            return 0;
        }
        // 数字栈
        Stack<Double> numStack = new Stack<>();
        // 符号栈
        Stack<Character> operStack = new Stack<>();
        String temp = "";
        for(int i=0; i<exp.length(); i++) {
            char ch = exp.charAt(i);
            // 收集+-操作符最后再进行计算
            switch (ch) {
                case '+':
                case '-':
                    if(temp.trim().matches("\\d+")) {
                        numStack.push(Double.parseDouble(temp.trim()));
                        temp = "";
                    }
                    // 操作符栈为空,直接入栈
                    if(!operStack.isEmpty()) {
                        // 判断优先级
                        char oper = operStack.peek();
                        if(oper == '-'){
                            numStack.push(numStack.pop() * -1);
                            operStack.pop();
                            operStack.push('+');
                        } else if(oper == '*' || oper == '/') {
                            // 栈内的优先级高, 先计算栈内的数据
                            _calc(numStack, operStack);
                        }
                    }
                    operStack.push(ch);
                    break;
                case '*':
                case '/':
                    if(temp.trim().matches("\\d+")) {
                        numStack.push(Double.parseDouble(temp.trim()));
                        temp = "";
                    }
                    char oper = operStack.peek();
                    if(oper == '-'){
                        numStack.push(numStack.pop() * -1);
                        operStack.pop();
                        operStack.push('+');
                    }

                    operStack.push(ch);
                    break;
                default:
                    temp += ch;
            }
        }
        numStack.push(Double.parseDouble(temp.trim()));
        _calc(numStack, operStack);
        _calc(numStack, operStack);
        return numStack.pop();
    }

    private static void _calc(Stack<Double> numberStack, Stack<Character> operStack) {
        // 判断空值
        if(operStack.isEmpty()) {
            return;
        }
        // 定义退出条件
        char startOper = operStack.peek();
        while(true) {
            if(operStack.isEmpty()) {
                break;
            }
            // 先查看当前的符号
            char ch = operStack.peek();
            if((startOper == '*' || startOper == '/') && (ch == '+' || ch == '-')) {
                break;
            }
            // 确定优先级之后,符号弹出
            operStack.pop();
            double num2 = numberStack.pop();
            double num1 = numberStack.pop();
            double ret = 0;
            switch (ch) {
                case '*':
                    ret = num1 * num2;
                    break;
                case '/':
                    ret = num1 / num2;
                    break;
                case '+':
                    ret = num1 + num2;
                    break;
                case '-':
                    ret = num1 - num2;
                    break;
            }
            numberStack.push(ret);
        }
    }
}
